package utils;

import java.io.File;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.IntConsumer;

import org.bson.Document;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

import lombok.extern.slf4j.Slf4j;
@Slf4j
public class GitUtils {
	
	
	private GitUtils() {}
	
	
	public static void saveCommits(File gitDir, String mongoDatabase, String commitsCollection
			, LocalDate startDate, LocalDate endDate)  {
		
		long days = startDate.until(endDate, ChronoUnit.DAYS);
		int step = 30;
		MongoDatabase db = MongoUtils.getDatabase(mongoDatabase);
		MongoCollection<Document> commitsColl = db.getCollection(commitsCollection);
		commitsColl.createIndex(new Document("sha",1));
		commitsColl.createIndex(new Document("author.name",1));
		commitsColl.createIndex(new Document("committer.date",1));
		AtomicLong count = new AtomicLong(0);
		AtomicLong prevCount = new AtomicLong(0);
		IntConsumer  daysConsumer = i->{
			String startTime = startDate.plusDays(i).toString();
			String endTime = startDate.plusDays(Math.min(days+1, i+step)).toString();
			log.info("getting commits from {} to {}:", startTime, endTime);
				
			List<Map<String, Object>> logs = null;
			try {
				logs = GitLogParser.getGitLogs(gitDir, startTime, endTime);
			} catch (Exception e) {
				log.error("get commits from {} to {} failed", startTime, endTime, e);
			}
			if(logs == null || logs.isEmpty()) {
				log.info("got 0 commits:{} to {}", startTime, endTime);
				return;
			}
			count.getAndAdd(logs.size());
			log.info("got {} commits:{} to {}", logs.size(), startTime, endTime);
			commitsColl.deleteMany(new Document("sha", new Document("$in", logs.stream().map(log->log.get("sha")).toList())));
			commitsColl.insertMany(logs.stream().map(Document::new).toList());
			if(count.get() - prevCount.get()>1000) {
				log.info("committed {} commits", count.get());
			}
			prevCount.set(count.get());
		};
		if(days/step>10) {
			var executor = Executors.newFixedThreadPool(8);
			for(int i=0;i<=days;i+=step) {
				final int j = i;
				executor.execute(()->daysConsumer.accept(j));
			}
			executor.shutdown();
			
		}else {
			for(int i=0;i<=days;i+=step) {
				daysConsumer.accept(i);
			}
		}
		
		
	}
	
	
	public static void main(String[] args) {
		
		String gitDir = "/home/ext2/git/dqb";
		String startDate = "2023-01-01";
		String endDate = "2023-12-31";
		String mongoDatabase = "dqb_commits";
		String commitsCollection = "commits";
		
		try {
			saveCommits(new File(gitDir), mongoDatabase, commitsCollection
					, LocalDate.parse(startDate), LocalDate.parse(endDate));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	

}
